Security News
Cloudflare Adds Security.txt Setup Wizard
Cloudflare has launched a setup wizard allowing users to easily create and manage a security.txt file for vulnerability disclosure on their websites.
@poppinss/prompts
Advanced tools
Module on top of enquirer with API for testing as well.
This module wraps enquirer and exposes the API to easily test prompts without pulling your hair.
For testing, we make use of Event Emitter instead of executing actual prompts and you can act on those events programmatically.
Please note: Only a subset of prompts are implemented. However, I am open to accept PR's for adding more.
ask(title: string, options?: TextPromptOptions)
secure(title: string, options?: TextPromptOptions)
confirm(title: string, options?: BooleanPromptOptions)
toggle(title: string, choices: [string, string], options?: TogglePromptOptions)
choice(title: string, choices: (string | {})[], options?: ChoicePromptOptions)
multiple(title: string, choices: (string | {})[], options?: MultiplePromptOptions)
autocomplete(title: string, choices: string[], options?: AutoCompletePromptOptions)
enum(title: string, options?: EnumPromptOptions)
When using enquirer, there is no simple way to test your code that makes use of prompts as prompts needs manual intervention. This module ships with a parallel implementation that uses the Event emitter to interact with prompts programmatically. For example:
You want to test a command that asks for the username and password and this is how you may go about writing it.
class MyCommand {
constructor(prompt) {
this.prompt = prompt
}
async run() {
const username = await this.prompt.ask('Enter account username', { name: 'username' })
const password = await this.prompt.ask('Enter account password', { name: 'password' })
console.log({ username, password })
}
}
During the tests, you can pass the emitter based prompt instance to your command as shown below:
import { FakePrompt } from '@poppinss/prompts'
const prompt = new FakePrompt()
prompt.on('prompt', (question) => {
if (question.name === 'username') {
question.answer('virk')
} else {
question.answer('secret-password')
}
})
const myCommand = new MyCommand(prompt)
await myCommand.run()
It is as simple as that. There is no need to make any code changes, just make use of the FakePrompt
class over Prompt
.
Install the package from the npm registry as follows:
npm i @poppinss/prompts
# yarn
yarn add @poppinss/prompts
import { Prompt } from '@poppinss/prompts'
const prompt = new Prompt()
const username = await prompt.ask('What is your username?')
const password = await prompt.secure('Enter account password')
const client = await prompt.choice('Choose installation client', ['npm', 'yarn'])
During tests, replace Prompt
with FakePrompt
and everything works as expected. However, do make sure that you listen for the prompt
event and answer every prompt, otherwise your tests will hang.
The following prompt types from enquirer are implemented. The method names exposed by this module are different (my personal preference).
ask(title: string, options?: TextPromptOptions)
Uses the input
prompt type. Optionally you can define the following options.
await prompt.ask('Choose account username', {
validate(answer) {
if (!answer || answer.length < 4) {
return 'Username is required and must be over 4 characters'
}
return true
},
})
Use the following code to answer prompt during tests
prompt.on('prompt', (question) => {
assert.equal(question.message, 'Choose account username')
question.answer('virk')
})
const username = await prompt.ask('Choose account username')
assert.equal(username, 'virk')
secure(title: string, options?: TextPromptOptions)
Uses the password
prompt type. You can define the same options as the ask
method.
await prompt.secure('Enter account password', {
validate(answer) {
if (!answer) {
return 'Password is required to login'
}
return true
},
})
Use the following code to answer prompt during tests
prompt.on('prompt', (question) => {
assert.equal(question.message, 'Enter account password')
question.answer('secret')
})
const password = await prompt.secure('Enter account password')
assert.equal(password, 'secret')
confirm(title: string, options?: BooleanPromptOptions)
Uses the confirm prompt. The prompt options are same as the ask
method.
await prompt.confirm('Want to delete files?')
Use the following code to answer prompt during tests
prompt.on('prompt', (question) => {
assert.equal(question.message, 'Want to delete files?')
// Say yes
question.accept()
// Say no
question.decline()
})
const deleteFiles = await prompt.confirm('Want to delete files?')
assert.isTrue(deleteFiles)
toggle(title: string, choices: [string, string], options?: TogglePromptOptions)
Use the toggle prompt. The prompt options are same as the ask
method.
await prompt.toggle('Want to delete files?', ['Yep', 'Nope'])
Use the following code to answer prompt during tests
prompt.on('prompt', (question) => {
assert.equal(question.message, 'Want to delete files?')
// Say yes
question.accept()
// Say no
question.decline()
})
const deleteFiles = await prompt.toggle('Want to delete files?', ['Yep', 'Nope'])
assert.isTrue(deleteFiles)
choice(title: string, choices: (string | {})[], options?: ChoicePromptOptions)
Uses the select prompt. The prompt options are same as the ask
method.
await prompt.choice('Select installation client', ['npm', 'yarn'])
Or pass the choice as an object
await prompt.choice('Select toppings', [
{
name: 'Jalapenos',
hint: 'Marinated in vinegar, will taste sour',
},
{
name: 'Lettuce',
hint: 'Fresh and leafy',
},
])
Use the following code to answer prompt during tests
prompt.on('prompt', (question) => {
assert.equal(question.message, 'Select installation client')
// pass index
question.select(0)
})
const client = await prompt.choice('Select installation client', ['npm', 'yarn'])
assert.equal(client, 'npm')
multiple(title: string, choices: (string | {})[], options?: MultiplePromptOptions)
Uses the multiselect prompt. The prompt options are same as the ask
method.
await prompt.multiple('Select base dependencies', ['@adonisjs/core', '@adonisjs/bodyparser'])
Or pass the choice as an object
await prompt.multiple('Select base dependencies', [
{
name: '@adonisjs/core',
message: 'Framework core',
},
{
name: '@adonisjs/bodyparser',
message: 'Bodyparser',
},
])
Use the following code to answer prompt during tests
prompt.on('prompt', (question) => {
assert.equal(question.message, 'Select base dependencies')
// pass indexes
question.multiSelect([0, 1])
})
const dependencies = await prompt.multiple('Select base dependencies', [
'@adonisjs/core',
'@adonisjs/bodyparser',
])
assert.deepEqual(dependencies, ['@adonisjs/core', '@adonisjs/bodyparser'])
autocomplete(title: string, choices: string[], options?: AutoCompletePromptOptions)
Uses the autocomplete prompt.
await prompt.autocomplete('Select country', ['India', 'USA', 'UK', 'Ireland', 'Australia'])
For multi-select, you can pass the multiple
property
await prompt.autocomplete('Select country', ['India', 'USA', 'UK', 'Ireland', 'Australia'], {
multiple: true,
})
Use the following code to answer prompt during tests
prompt.on('prompt', (question) => {
assert.equal(question.message, 'Select country')
// pass indexes
question.select(1)
})
const country = await prompt.autocomplete('Select country', [
'India',
'USA',
'UK',
'Ireland',
'Australia',
])
assert.equal(country, 'USA')
enum(title: string, options?: EnumPromptOptions)
Similar to the ask
prompt, but allows comma (,) separated values. Uses the list prompt.
await prompt.enum('Define tags', {
hint: 'Accepts comma separated values',
})
Use the following code to answer prompt during tests
prompt.on('prompt', (question) => {
assert.equal(question.message, 'Define tags')
question.answer('nodejs,javascript')
})
const tags = await await prompt.enum('Define tags')
assert.deepEqual(tags, ['nodejs', 'javascript'])
FAQs
Wrapper over enquirer with better support for testing
The npm package @poppinss/prompts receives a total of 25,385 weekly downloads. As such, @poppinss/prompts popularity was classified as popular.
We found that @poppinss/prompts demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Cloudflare has launched a setup wizard allowing users to easily create and manage a security.txt file for vulnerability disclosure on their websites.
Security News
The Socket Research team breaks down a malicious npm package targeting the legitimate DOMPurify library. It uses obfuscated code to hide that it is exfiltrating browser and crypto wallet data.
Security News
ENISA’s 2024 report highlights the EU’s top cybersecurity threats, including rising DDoS attacks, ransomware, supply chain vulnerabilities, and weaponized AI.